package com.lanchetech.merchant.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.CategoryReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.CategoryInfoResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.CategoryEditVO;
import com.lanchetech.bean.vo.ShopCategoryEditVO;
import com.lanchetech.common.enums.CategoryTypeEnum;
import com.lanchetech.common.enums.DeletedEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.merchant.service.CategoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    FrontBackCategoryMapper frontBackCategoryMapper;

    @Autowired
    CategoryBrandMapper categoryBrandMapper;

    @Autowired
    CategorySpecMapper categorySpecMapper;

    @Autowired
    AttributeMapper attributeMapper;

    @Autowired
    SpuAttributeMapper spuAttributeMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ShopCategoryMapper shopCategoryMapper;


    @Override
    public ResultData<List<Category>> getTwoLevelCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetTwoLevelCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.getTwoLevelCategoryList(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getAllCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetAllCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.findAllByType(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getRootCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetRootCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.findAllRootByType(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getChildrenCategory(Long id) {
        return new ResultData<>(categoryMapper.findAllByPid(id));
    }

    @Override
    public ResultData<CategoryEditVO> getCategoryDetail(Long id) {
        Category category = categoryMapper.selectByPrimaryKey(id);
        CategoryEditVO categoryEditVO = new CategoryEditVO();
        BeanUtils.copyProperties(category, categoryEditVO);
        if (CategoryTypeEnum.FRONT.getType().equals(category.getType())) {
            List<FrontBackCategory> list = frontBackCategoryMapper.findAllByFrontId(category.getId());
            List<Long> result = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                result.add(list.get(i).getBackId());
            }
            categoryEditVO.setRelateCategory(result);
        } else {
            // 品牌
            List<CategoryBrand> brandList = categoryBrandMapper.findAllByCategoryId(id);
            List<Long> brandIds = new ArrayList<>();
            for (int i = 0; i < brandList.size(); i++) {
                brandIds.add(brandList.get(i).getBrandId());
            }

            // 销售属性
            List<CategorySpec> specList = categorySpecMapper.findAllByCategoryId(id);
            List<Long> specIds = new ArrayList<>();
            for (int i = 0; i < specList.size(); i++) {
                specIds.add(specList.get(i).getSpecId());
            }

            // 自然属性
            List<Attribute> attributes = attributeMapper.findAllByCategoryId(id);
            categoryEditVO.setBrandIds(brandIds);
            categoryEditVO.setSpecIds(specIds);
            categoryEditVO.setAttributeList(attributes);
        }

        return new ResultData<>(categoryEditVO);
    }

    @Override
    public ResultData<CategoryInfoResp> getCategoryInfo(Long id) {
        CategoryInfoResp resp = new CategoryInfoResp();
        resp.setAttributeList(attributeMapper.findAllByCategoryId(id));
        resp.setSpecList(categorySpecMapper.findAllSpecByCategoryId(id));
        resp.setBrandList(categoryBrandMapper.findAllBrandByCategoryId(id));
        return new ResultData<>(resp);
    }

    @Override
    public ResultData<List<ShopCategory>> getAllShopCategoryList() {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ValueOperations<String, List<ShopCategory>> operations = redisTemplate.opsForValue();
        String key = "GetAllShopCategoryList:" + merchant.getTenantId();
        List<ShopCategory> result = operations.get(key);
        if (result == null) {
            result = shopCategoryMapper.findall();
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public BaseResp editShopCategory(ShopCategoryEditVO shopCategoryEditVO) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ShopCategory shopCategory = new ShopCategory();
        BeanUtils.copyProperties(shopCategoryEditVO, shopCategory);

        deleteRedisByKey("GetAllShopCategoryList:" + merchant.getTenantId());

        if (shopCategory.getId() == null) {
            shopCategory.setDeleted((byte) 0);
            shopCategory.setCreatedAt(new Date());
            shopCategory.setUpdatedAt(new Date());
            shopCategoryMapper.insert2(shopCategory);
        } else {
            shopCategory.setUpdatedAt(new Date());
            shopCategoryMapper.updateByPrimaryKeySelective(shopCategory);
        }

        return new BaseResp();
    }

    @Override
    public BaseResp deleteShopCategory(Long id) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopCategoryMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);
        deleteRedisByKey("GetAllShopCategoryList:" + merchant.getTenantId());
        return new BaseResp();
    }

    /**
     * 模糊删除redis，支持通配符
     *
     * @param key
     */
    private void deleteRedisByKey(String key) {
        Set<String> keys = redisTemplate.keys(key);
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    public ResultData<ShopCategory> getShopCategoryDetail(Long id) {
        return new ResultData<>(shopCategoryMapper.selectByPrimaryKey(id));
    }

    @Override
    public ResultData<BasePageResp<Category>> getCategoryPage(CategoryReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Category> list = categoryMapper.findAllAdminPage(req);
        return PageHelpUtil.buildPage(list, page);
    }
}